// $Id: request.c 81 2011-04-24 07:37:10Z cedric.shih@gmail.com $
/*
 * Copyright (C) 2010 Cedric Shih <cedric.shih@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdlib.h>
#include <string.h>

#include <nio.h>
#include <nio/buffer.h>

#include "headers.h"
#include "request.h"
#include "codec/server.h"

#include "niohttp/test.h"

#define BUFFER_SIZE 1024

static struct niohttp_request_decoder *decoder;
static struct niobuffer *buffer;

static void test_setup(void)
{
	decoder = niohttp_request_decoder_new();
	buffer = niobuffer_new(BUFFER_SIZE);
}

static void test_teardown(void)
{
	niobuffer_free(buffer);
	niohttp_request_decoder_free(decoder);
}

static void test_init(void)
{
	TEST_ASSERT_NOT_NULL(buffer);
	TEST_ASSERT_NOT_NULL(decoder);
}

static const char *normal1 = "GET / HTTP/1.0\r\n"
		"Host: www.google.com\r\n"
		"Connection: close\r\n"
		"User-Agent: Web-sniffer/1.0.37 (+http://web-sniffer.net/)\r\n"
		"Accept-Encoding: gzip\r\n"
		"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n"
		"Cache-Control: no-cache\r\n"
		"Accept-Language: de,en;q=0.7,en-us;q=0.3\r\n"
		"Referer: http://web-sniffer.net/\r\n"
		"\r\n";

static void test_normal1(void)
{
	int rc;
	size_t pos, i, len;
	struct niohttp_request *req;

	rc = niohttp_request_decoder_setup(decoder);
	TEST_ASSERT_EQUAL_INT(0, rc);

	niobuffer_clear(buffer);

	len = strlen(normal1);
	rc = niobuffer_puts(buffer, (unsigned char *)normal1, len);
	TEST_ASSERT_EQUAL_INT(0, rc);
	pos = niobuffer_position(buffer);

	niobuffer_flip(buffer);

	rc = niohttp_request_decoder_parse(decoder, buffer, &req);
	TEST_ASSERT_EQUAL_INT(0, rc);
	TEST_ASSERT_EQUAL_INT(pos, niobuffer_position(buffer));
	TEST_ASSERT_NOT_NULL(req);

	TEST_ASSERT_EQUAL_INT(NIOHTTP_REQ_CONTENT, decoder->state);
	TEST_ASSERT_NOT_NULL(decoder->request->method);
	TEST_ASSERT_EQUAL_STRING("GET", decoder->request->method);
	TEST_ASSERT_NOT_NULL(decoder->request->uri);
	TEST_ASSERT_EQUAL_STRING("/", decoder->request->uri);
	TEST_ASSERT_NOT_NULL(decoder->request->protocol);
	TEST_ASSERT_EQUAL_STRING("HTTP", decoder->request->protocol);
	TEST_ASSERT_NOT_NULL(decoder->request->version.string);
	TEST_ASSERT_EQUAL_STRING("1.0", decoder->request->version.string);
	TEST_ASSERT_EQUAL_INT(1, decoder->request->version.major);
	TEST_ASSERT_EQUAL_INT(0, decoder->request->version.minor);
	TEST_ASSERT_EQUAL_INT(8, niohttp_headers_size(decoder->request->header));

	niohttp_request_decoder_teardown(decoder);

	rc = niohttp_request_decoder_setup(decoder);
	TEST_ASSERT_EQUAL_INT(0, rc);

	niobuffer_clear(buffer);

	for (i = 0; i < len; i++) {
		rc = niobuffer_put(buffer, normal1[i]);
		TEST_ASSERT_EQUAL_INT(0, rc);
		pos = niobuffer_position(buffer);

		niobuffer_flip(buffer);

		rc = niohttp_request_decoder_parse(decoder, buffer, &req);
		TEST_ASSERT_EQUAL_INT(0, rc);
		TEST_ASSERT_EQUAL_INT(pos, niobuffer_position(buffer));
		if (i < len - 1) {
			TEST_ASSERT_NULL(req);
		}
		rc = niobuffer_set_limit(buffer, niobuffer_capacity(buffer));
	}

	TEST_ASSERT_EQUAL_INT(NIOHTTP_REQ_CONTENT, decoder->state);
	TEST_ASSERT_NOT_NULL(decoder->request->method);
	TEST_ASSERT_EQUAL_STRING("GET", decoder->request->method);
	TEST_ASSERT_NOT_NULL(decoder->request->uri);
	TEST_ASSERT_EQUAL_STRING("/", decoder->request->uri);
	TEST_ASSERT_NOT_NULL(decoder->request->protocol);
	TEST_ASSERT_EQUAL_STRING("HTTP", decoder->request->protocol);
	TEST_ASSERT_NOT_NULL(decoder->request->version.string);
	TEST_ASSERT_EQUAL_STRING("1.0", decoder->request->version.string);
	TEST_ASSERT_EQUAL_INT(1, decoder->request->version.major);
	TEST_ASSERT_EQUAL_INT(0, decoder->request->version.minor);
	TEST_ASSERT_EQUAL_INT(8, niohttp_headers_size(decoder->request->header));

	niohttp_request_decoder_teardown(decoder);
}

TestRef niohttp_request_codec_test(void)
{
	EMB_UNIT_TESTFIXTURES(fixtures) {
		new_TestFixture("niohttp_request_codec_test_init", test_init),
		new_TestFixture("niohttp_request_codec_test_normal1",
				test_normal1),
	};
	EMB_UNIT_TESTCALLER(test_case, "niohttp_request_codec_test", test_setup, test_teardown, fixtures);
	return (TestRef)&test_case;
}
